#pragma once
#include <iostream>
#include <vector>
#include <queue>
#include <mutex>
#include <functional>


#include "task.hpp"
#include "Thread.hpp"
const static int N = 5;

// typedef void(*func_t)(int,int); 
template <class T>

class ThreadPool
{
public:
    ThreadPool(int num = N) : num_(num)
    {
        pthread_mutex_init(&mtx_, nullptr);
        pthread_cond_init(&cond_, nullptr);
    }
    void init()
    {
        for (int i = 0; i < num_; i++)
        {
            threads_.push_back(Thread(i,threadRoutine,this));
        }
    }
    void start()
    {
     for(int i=0;i<num_;i++)
     {
        threads_[i].run();
     }   
    }
    static void threadRoutine(void *args)
    {
        pthread_detach(pthread_self());
        ThreadPool<T> *tp = static_cast<ThreadPool<T> *>(args);
        while (true)
        {
            tp->Lock();

            while (tp->IsEmpty())
            {
                // 等待
                tp->ThreadWait();
            }

            T t;
            t=tp->PopTask();
            tp->Unlock();

            t(); //处理任务不需要在临界区中处理
            // tp->callback_(t.GetResult(),t.GetExitCode());
            std::cout<<t.formatArg()<<t.formatRes()<<std::endl;

        }
    }
    T PopTask() // 走到这一定是只有一个线程 不需要加锁
    {
        T t = tasks_.front();
        tasks_.pop();
        return t;
    }
    // func_t callback(int result,int code)
    // {
    //     callback_(t.GetResult,t.GetExitCode);
    // }
    bool IsEmpty()
    {
        return tasks_.empty();
    }

    void Lock()
    {
        pthread_mutex_lock(&mtx_);
    }
    void Unlock()
    {
        pthread_mutex_unlock(&mtx_);
    }
    void ThreadWait()
    {
        pthread_cond_wait(&cond_, &mtx_);
    }
    void ThreadWakeUp()
    {
        pthread_cond_signal(&cond_);
    }
    void PushTask(const T &task)
    {
        Lock();
        tasks_.push(task);
        ThreadWakeUp();
        Unlock();
    }
    
    ~ThreadPool()
    {
        for(auto & t:threads_)
        {
            t.join(); 
        }
        pthread_mutex_destroy(&mtx_);
        pthread_cond_destroy(&cond_);
    }

private:
    int num_;
    std::vector<Thread> threads_;
    std::queue<T> tasks_; // 使用stl自动扩容的特性,充当临界资源的角色
    pthread_mutex_t mtx_;
    pthread_cond_t cond_;
    // func_t callback_;
};